<?php

require_once 'Autoloader/Exception.class.php';

/**
 * Pluggable autoloader for Rapide libraries
 * 
 * Automatically loads classes if are needed. Pluggable interfece allows
 * exetending the autoloader.
 *
 */
class Rapide_Autoloader
{
	/**
	 * Extension for class files
	 */
	const LIB_EXTENSION = '.class.php';

	static private $_oInstance;

	private $_aPlugins = array();

	private function __construct()
	{
	}

	/**
	 * Get instance of object
	 *
	 * @return Rapide_Autoloader
	 */
	static public function getInstance()
	{
		if(!self::$_oInstance instanceof self)
		{
			self::$_oInstance = new self;
		}
		
		return self::$_oInstance;
	}

	/**
	 * Register plugin for loading classes
	 *
	 * @param Rapide_Autoloader_Plugin_Interface $oPlugin
	 */
	public function registerPlugin(Rapide_Autoloader_Plugin_Interface $oPlugin)
	{
			$this->_aPlugins[] = $oPlugin;
	}

	/**
	 * Load class file for given class name
	 *
	 * @param string $sClassName
	 * @return boolean true if class file has been loaded
	 */
	public function load($sClassName)
	{
		$bLoaded = $this->_load($sClassName);
		
		if(!$bLoaded)
		{
			foreach($this->_aPlugins as $oPlugin)
			{
				if($oPlugin->load($sClassName))
				{
					$bLoaded = true;
					break;
				}
			}
		}
		
		if(!$bLoaded)
		{
			
			eval("class $sClassName {}");

			$sError = sprintf('Class %s not found', $sClassName);
			throw new Rapide_Exception($sError);
		}

		// on failure: php will display fatal error
		return $bLoaded;
	}

	private function _load($sClassName)
	{
		$sClassFile = _DIR_RAPIDE . '/' . self::prepareClassFile($sClassName);

		if(!file_exists($sClassFile))
		{
			return false;
		}

		require_once $sClassFile;
		
		return class_exists($sClassName, false) || interface_exists($sClassName, false);
	}

	public static function prepareClassFile($sClassName)
	{
		$sClassFile = str_replace('_', '/', $sClassName);
		$sClassFile = $sClassFile . self::LIB_EXTENSION;
		
		return $sClassFile;
	}
}

?>